package com.demo.wormhole.autoconfiguration.datasource.mybatis;

import com.demo.wormhole.component.datasource.route.DynamicDataSourceContextHolder;
import com.demo.wormhole.component.datasource.route.WormholeDynamicDataSource;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@ConditionalOnClass({SqlSessionFactoryBean.class})
@ConditionalOnBean(name = {"primaryDatasource", "shadowDatasource"})
@Configuration
public class WormholeMybatisConfiguration {
    
    @Resource(name = "primaryDatasource")
    private DataSource primary;
    @Resource(name = "shadowDatasource")
    private DataSource shadow;
    
    @Value("${mybatis.mapper-locations}")
    private String mapperLocations;
    
    @Value("${mybatis.type-aliases-package}")
    private String typeAliasesPackage;
    
    @Bean("dynamicDataSource")
    public DataSource dynamicDataSource() {
        WormholeDynamicDataSource dynamicDataSource = new WormholeDynamicDataSource();
        Map<Object, Object> dataSourceMap = new HashMap<>(2);
        dataSourceMap.put(DynamicDataSourceContextHolder.PRIMARY_DB, primary);
        dataSourceMap.put(DynamicDataSourceContextHolder.SHADOW_DB, shadow);
        // 将 master 数据源作为默认指定的数据源
        dynamicDataSource.setDefaultDataSource(primary);
        // 将 master 和 slave 数据源作为指定的数据源
        dynamicDataSource.setDataSources(dataSourceMap);
        return dynamicDataSource;
    }
    
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        // 配置数据源，此处配置为关键配置，如果没有将 dynamicDataSource作为数据源则不能实现切换
        sessionFactory.setDataSource(dynamicDataSource());
        if (StringUtils.isNotEmpty(typeAliasesPackage)) {
            sessionFactory.setTypeAliasesPackage(typeAliasesPackage);    // 扫描Model
        }
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sessionFactory.setMapperLocations(resolver.getResources(mapperLocations));    // 扫描映射文件
        return sessionFactory;
    }
    
    @Bean
    public PlatformTransactionManager transactionManager() {
        // 配置事务管理, 使用事务时在方法头部添加@Transactional注解即可
        return new DataSourceTransactionManager(dynamicDataSource());
    }
}
